package cn.comtom.ewbs.signature.common.utils;

import cn.hutool.core.lang.Console;
import cn.hutool.crypto.asymmetric.SM2;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sun.jna.Library;
import com.sun.jna.Native;
import lombok.Data;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;


/**
 * @author 码农liuhy
 *
 */
@Data
@Slf4j
//@Resource
//@Scope("singleton")
public class SM2Util {

	//@Value("${sign.softalg.certNo}")
	private String certNo;

	//@Value("${sign.softalg.priviteKey}")
	private String priviteKey;

	//@Value("${sign.softalg.publicKey}")
	private String publicKey;
	public SM2Util(){

	}
	public SM2Util(String certNo,String priviteKey,String publicKey){
		this.certNo=certNo;
		this.priviteKey=priviteKey;
		this.publicKey=publicKey;
	}

	 @Data
	 @ToString
	 static class SM2Req{
	 	// 0 ex签名， 1 ex验签,2 签名，3 验签
	 	private int cmd;
	 	//需签名数据
	 	private String base64;
		//签名值
		private String sign;
	 	//私钥
	 	private String privite_key;
	 	//公钥
	 	private String public_key;
	 	//证书编号
	 	private String id;

	 }

	 @Data
	 @ToString
	static class SM2Resp{
		//签名/验签结果
		private Integer Result;

		private String ResultStr;
		//签名值
		private String sign;
	}

    public interface SM2I extends Library {

        // DLL文件默认路径为项目根目录，若DLL文件存放在项目外，请使用绝对路径。（此处：(Platform.isWindows()?"msvcrt":"c")指本地动态库msvcrt.dll）
        SM2I INSTANCE = (SM2I) Native.loadLibrary("sm2",SM2I.class);

        // 声明将要调用的DLL中的方法,可以是多个方法(此处示例调用本地动态库msvcrt.dll中的printf()方法)
        String SM2_Json(String jsonStr);
    }

	/**
	 * 签名
	 * @param base64Data
	 * @return
	 */
	public String sign(String base64Data) {
	    synchronized (this.getClass()) {
			SM2Req sm2Req = new SM2Req();
			sm2Req.setCmd(0);
			sm2Req.setBase64(base64Data);
			sm2Req.setPrivite_key(priviteKey);
			sm2Req.setPublic_key(publicKey);
			sm2Req.setId(certNo);
			String result = SM2I.INSTANCE.SM2_Json(JSON.toJSONString(sm2Req));
			log.info("SM2Util.sign,sm2Req:{},result:{}",JSON.toJSONString(sm2Req),result);
			SM2Resp sm2Resp = JSONObject.parseObject(result,SM2Resp.class);
			if(sm2Resp!=null){
				return sm2Resp.getSign();
			}
			return null;
	    }
	}

	/**
	 * 验签
	 * @param base64Data
	 * @param base64sign
	 * @return
	 */
	public boolean verifySign(String base64Data, String base64sign,String publicKeyNo,String publicKeyP) {
		synchronized (this.getClass()) {
			SM2Req sm2Req = new SM2Req();
			sm2Req.setCmd(1);
			sm2Req.setBase64(base64Data);
			sm2Req.setSign(base64sign);
			//sm2Req.setPrivite_key(priviteKey);
			sm2Req.setPublic_key(publicKeyP);
			sm2Req.setId(publicKeyNo);
			String result = SM2I.INSTANCE.SM2_Json(JSON.toJSONString(sm2Req));
			log.info("SM2Util.verifySign,sm2Req:{},result:{}",JSON.toJSONString(sm2Req),result);
			SM2Resp sm2Resp = JSONObject.parseObject(result,SM2Resp.class);
			if(sm2Resp != null){
				return sm2Resp.getResult()==0;
			}
			return false;
		}
	}

	public boolean verfyFileSign(String dataHex, String signHex, String publicKeyP){
		String publicKeyX = publicKeyP.substring(0,64);
		String publicKeyY = publicKeyP.substring(64);
		final SM2 sm2 = new SM2(priviteKey, publicKeyX, publicKeyY);
		sm2.usePlainEncoding();
		boolean verify = sm2.verifyHex(dataHex, signHex);
		Console.log("SM2util.verfyFileSign.publicKeyP:{}",publicKeyP);
		Console.log("SM2util.verfyFileSign.dataHex:{}",dataHex);
		Console.log("SM2util.verfyFileSign.signHex:{}",signHex);
		return verify;
	}

	public String getFileSign(String dataHex){
		Console.log("SM2Util.getFileSign.dataHex:{}",dataHex);
		Console.log("SM2Util.getFileSign.publicKey:{}",publicKey);
		String publicKeyX = publicKey.substring(0,64);
		String publicKeyY = publicKey.substring(64);
		final SM2 sm2 = new SM2(priviteKey, publicKeyX, publicKeyY);
		sm2.usePlainEncoding();
		String sign = sm2.signHex(dataHex);
		Console.log("SM2Util.getFileSign.sign:{}",sign);
		return sign;
	}
//	public static String x = "E45FB09A87658BF8D92D0C1B391D953C66598AEFF8EEE61A88AD993F7F239565";
//	public static String y = "1CCFED6465F5062778CFC396D4D9DFC44C2040B8B0E615916ED63B45465753E6";
	public static void main(String[] args) {
		String p = "E45FB09A87658BF8D92D0C1B391D953C66598AEFF8EEE61A88AD993F7F2395651CCFED6465F5062778CFC396D4D9DFC44C2040B8B0E615916ED63B45465753E6";
		Console.log(p.substring(0,64));
		Console.log(p.substring(64));
	}
    
}
